iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
自我挑戰組

30天FUME TO FHIR轉換實戰 - 從入門到燃燒殆盡系列 第 18

[FUME TO FHIR] 18 FUME Community 安裝, 環境設定

  • 分享至 

  • xImage
  •  

VI.FUME

18 FUME Community 安裝, 環境設定

既然FUME Designer要付費才能使用,我們要在地端使用FUME就只能安裝FUME Community(FUME Engine),

https://github.com/Outburn-IL/fume-community/tree/main

將整包透過git或download下載後,在docker-compose.yml中選擇加入原先建置的HAPI FHIR services

docker-compse.yml:

version: "3.9"

services:
  fume-server:
    container_name: fume
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "42420:42420"
    volumes:
      - "./snapshots:/usr/src/app/snapshots"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "10"
        compress: "true"
    env_file:
      - ./.env
    environment:
      - NODE_TLS_REJECT_UNAUTHORIZED=0
    depends_on:
      - fhir

  db:
    container_name: fhirdb
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: admin
      POSTGRES_USER: admin
      POSTGRES_DB: hapi
    ports:
      - "5432:5432"

  fhir:
    container_name: hapi-fhir
    image: hapiproject/hapi:latest
    ports:
      - "8080:8080"
    volumes:
      - ./custom:/custom
    environment:
      HAPI_FHIR_USERNAME : admin
      HAPI_FHIR_PASSWORD : admin
      hapi.fhir.ig_runtime_upload_enabled: true 
      hapi.fhir.custom_content_path: /custom
      profiles.active: r4
      spring.datasource.url: 'jdbc:postgresql://fhirdb:5432/hapi'
      spring.datasource.username: admin
      spring.datasource.password: admin
      spring.datasource.driverClassName: org.postgresql.Driver
      spring.jpa.properties.hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect
      spring.jpa.properties.hibernate.search.enabled: false
    
      
    depends_on:
      - db

   
(modified from hackmd.io/@hongyu0324)

接著修改.env,在fume-community-main中可以看到有兩個檔案,分別對應stateful與stateless:

.env.example.stateful

.env.example.stateless

這邊指的是FUME Engine本身有沒有要跟FHIR Server協作,來看檔案的幾個比較重要的內容:

SERVER_STATELESS=false <- true = stateless / false = stateful ,用來控制是否與FHIR Server協作

SERVER_PORT=42420 <- fume的port位址

#FHIR_SERVER_BASE=http://localhost:8080/fhir <- FHIR Server的位址,使用stateful記得要輸入,

在docker中的位址要輸入service的名稱,如
FHIR_SERVER_BASE=http://fhir:8080/fhir

FHIR_SERVER_AUTH_TYPE=BASIC <- 如果你的FHIR Server有進行權限控制,記得給FUME輸入FHIR Server的帳號
FHIR_SERVER_UN=admin
FHIR_SERVER_PW=admin

FHIR_VERSION=4.0.1 <- FHIR的版本,這裡寫4.0.1不用動

SEARCH_BUNDLE_PAGE_SIZE=20 <- Search的時候單頁的最大Resource數量

FHIR_PACKAGES=il.core.fhir.r4@0.11.0,hl7.fhir.us.core <- 匯入IG,筆者沒有使用過但推測這個功能僅是將profile轉換為template使用

該專案的docs/getting-started.md還有另一條選擇可以使用,透過nodejs內嵌的方式執行轉換,但筆者實際測試不能使用太大的內容,所以並未使用這個方法。

在挑選完要使用stateless / stateful後,接下來就是cd到fume-community-main執行docker compose

cd YOURDIRECTORY/fume-community-main

docker compose up

這邊要注意一點是,透過compose啟動整個服務,會將三個(hapi fhir, fume, db)一起啟動,但這會有一個小問題

正常來說,HAPI FHIR Server的啟動時間會遠大於FUME,這也導致了當FUME已經啟動完成時,FUME還不能抓取到FHIR Server的部署位置,

因此又會跑回stateless的模式運作,由於HAPI FHIR並沒有一個可以記錄health check的方式,docker無法知道HAPI FHIR的確切啟動完成時間,

stateful暫時的解法有兩個,第一個是Compose去耦合,把HAPI FHIR與Fume分別以兩個服務啟動,或是等到HAPI FHIR完全啟動後,再啟動/重啟FUME,

FUME Community若以stateful啟動,在啟動時會去向FHIR Server請求StructureMap與ConceptMap等Resource,作為用來轉換的預先載入資源。

如果是stateless的話,FUME就只會單純啟動,無論使用哪種方式,要確認啟動的最好方式就是

GET | http://localhost:42420

如果FUME是正常啟動的話應該會丟回FUME的版本,

{
    "fume_version": "FUME Community v2.18.5"
}

到這一步FUME就算是正式啟動完成了,那下一步呢?

前面我們提到過,FUME的組成由輸入的JSON資料與FUME Mapping所構成,
在REST的架構上的輸入方法在這一步會因為選擇的模式而有區別

--

首先是stateful,因為輸入的方式會稍微簡單一些,但兩個模式要做的事情是很類似的

在FUME官方的說明中,在FUME Designer Playground中儲存FUME Mapping,自訂名稱。

接著在右上方的FUME欄位中 輸入

$resolve("StructureMap/剛才的儲存名稱")

右下方的Resource就會返回一個StructureMap,把這個Resource上傳到本地的FHIR Server,並且重啟FUME Engine

可以在FUME的啟動過程中觀測到FUME有從FHIR Server拿到這個Resource,當FUME重新啟動完成後,

在POSTMAN中執行

POST | http://localhost:42420/Mapping/剛才的StructureMap的ResourceID

Headers : Content-Type -> application/json
Body    : raw -> JSON -> 把原先在FUME Designer中左側的那一整包輸入的資料貼上去按下Send送出,

下方的Response Body即為轉換完成的FHIR結果。

--

stateless的方法也很簡單,因為FUME此時沒有FHIR Server能夠借Resource了,在輸入部分,要改成

POST | http://localhost:42420/
Headers : Content-Type -> application/json
Body    : raw -> JSON -> 

{
 "input" : "",
 "fume" : ""
}

其中input為輸入的JSON,就是FUME Designer中左側那一整包輸入資料;
最快的方式就是把透過$resolve("StructureMap/剛才的儲存名稱")得到的StructureMap中的
group.rule.extension.valueExpression.expression欄位中複製出來貼到body.fume裡面

下方的Response Body即為轉換完成的FHIR結果。

這兩個方式看起來都不錯,但有一個環節會出問題,
無論透過哪個方式,都免不了要將自己撰寫的FUME Mapping存檔在Playground中,再用$resolve抽取出來StructureMap,
這樣會造成資料外洩的問題,有沒有方法能夠將這一步取代掉的,當然有,

最簡單暴力的方法就是自己刻一個適用於FUME的StructureMap,
然後將FUME Mapping字串化後放入group.rule.extension.valueExpression.expression,
再上傳FHIR Server讓FUME來讀取

又或者是stateless直接將自己的FUME Mapping字串化塞進body.fume中,

總之,這個部分可以自己透過程式來整理完成,實現方法諸多在這裡就不提供

明天開始來講要怎麼寫FUME Mapping囉,今天寫的篇幅偏長,但內容的確是這麼多


上一篇
[FUME TO FHIR] 17 FUME Designer
下一篇
[FUME TO FHIR] 19 FUME Mapping Language(FLASH)
系列文
30天FUME TO FHIR轉換實戰 - 從入門到燃燒殆盡30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言